/*****************************************************
** Author: 
** Date: 2020-04-01
*
*****************************************************/

#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>

#define CRC16_TABLE_SIZE 16
#define CRC32_TABLE_SIZE 256


/**
 * @brief
 * @param  None
 * @retval None
 */
static void hexdump(unsigned char *buf, int len, const char *str, ...)
{
	int i;

	va_list args;
 	va_start(args, str);
	vprintf(str, args);
	va_end(args);

	for (i = 0; i < len; ++i) {
		if (i % 16 == 0) {
			// printf("\n%p:", buf + i);
			printf("\n");
		}
		printf(" %02x", buf[i]);
	}
	printf("\n");
}

static void soft_crc16_init(uint32_t *table)
{
	uint16_t crc = 0;
	uint8_t i;
	uint8_t j;

	for (j = 0; j < CRC16_TABLE_SIZE; j++) {
		crc = 0;
		for (i = 0x01; i != 0x10; i <<= 1) {
			if ((crc & 0x0001) != 0) {
				crc >>= 1;
				crc ^= 0x8408;
			} else {
				crc >>= 1;
			}
			if ((j & i) != 0) {
				crc ^= 0x8408;
			}
		}
		table[j] = crc;
	}
}

uint16_t dna_soft_crc16(const void *__buf, uint16_t len)
{
	static uint32_t crc_table[CRC16_TABLE_SIZE];
	static unsigned char init_done = 0;
	const uint8_t *buf = __buf;
	uint16_t crc = 0;
	uint8_t crc_H8;

	if (!init_done) {
		// create table
		soft_crc16_init(crc_table);
		hexdump(crc_table, sizeof(crc_table), "crc16 %d", sizeof(crc_table));
		init_done = !0;
	}

	while (len--) {
		crc_H8 = (uint8_t)(crc & 0x000F);
		crc >>= 4;
		crc ^= crc_table[crc_H8 ^ (*buf & 0x0F)];
		crc_H8 = (uint8_t)(crc & 0x000F);
		crc >>= 4;
		crc ^= crc_table[crc_H8 ^ (*buf >> 4)];
		buf++;
	}

	return crc;
}

static void soft_crc32_init(uint32_t *table)
{
	const static int rcrc32 = 0xEDB88320;
	unsigned int crc = 0;
	unsigned char i;
	unsigned int j;

	for (j = 0; j < CRC32_TABLE_SIZE; j++) {
		crc = 0;
		for (i = 0x01; i != 0x00; i <<= 1) {
			if ((crc & 0x00000001) != 0) {
				crc >>= 1;
				crc ^= rcrc32;
			} else {
				crc >>= 1;
			}
			if ((j & i) != 0)
				crc ^= rcrc32;
		}
		table[j] = crc;
	}
}

uint32_t dna_soft_crc32(const void *__data, int data_size, uint32_t crc)
{
#if 0
	static uint32_t crc_table[CRC32_TABLE_SIZE];
	static unsigned char init_done = 0;
	const uint8_t *data = __data;
	unsigned int result = crc;
	unsigned char crc_H8;

	if (!init_done) {
		// create table
		soft_crc32_init(crc_table);
		init_done = !0;
	}

	while (data_size--) {
		crc_H8 = (unsigned char)(result & 0x000000FF);
		result >>= 8;
		result ^= crc_table[crc_H8 ^ (*data)];
		data++;
	}

	return result;
#else

#define CRCPOLY_LE 0xedb88320
	const unsigned char * data = __data;
	int i;
	while (data_size--) {
		crc ^= *data++;
		for (i = 0; i < 8; i++)
			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
	}
	return crc;

#endif
}

/* End of file */



